/******************************************************************************
*filename: dstruct.h
*Holds the seeder,leecher and file_part data structures.
*This file must be included in both the sparta torrent program and the tracker.
*as well.
*part-size = 64kb.(pieces)
*
*Author : Neeraj Naik
*Date:4th Nov 2010
*******************************************************************************/

#ifndef DSTRUCT
#define DSTRUCT

#define MAX_SEEDS 10
#define MAX_LEECHES 10
#define PARTSIZE 65536


// file_part is a linked list.
struct file_part{

        struct file_part *next;

	char* filename;		//name of the file to which the part belongs
	int part_num;		//part number (can be used for somethng like hash checking)
	
	FILE *data_ptr;		//ptr to the file created for this part.ie whr the data of this part is stored.
				//file descriptor for FILE* data_ptr.

	int offset;		//will hold the offset to the starting point of the part. each part being 64kb.
		
	struct seeder seeder_list[MAX_SEEDS];	//list of seeders.
	struct leecher leecher_list[MAX_LEECHES];	//
	
	float percent_downloaded;
	enum status{SEEDING,COMPLETE,LEECHING,PENDING}download;
		
}*head,*curr,*tail;

int add_to_list(???);//unsure for the parameters for this part.
enum check_file(struct file_part *head,enum chck_status);
int join_file(struct file_part *head);//once all parts are downloaded, this fn will join and make a complete file.after downloading, this function will first cross check 'filename' & 'part_num' to see if file is in order.
void print_list();//might be needed while debugging.
static float calc_percent(FILE * ptr);// HELPER FUNCTION:calculates the data in a file part

/*****************************JOIN_FILE***************************/
//first checks if all parts are in order and all parts are complete.
// returns 0 if file joined properly.
// 	   1 if parts not in order.
//	   2 if parts incomplete.
int join_file(struct file_part *head)
{
	struct file_part *temp = head;
	int i=1;flag = 0;//ALL OK
	while(!flag && temp->next){
		if(temp->part_num == i){
			temp = temp->next;
			i++;
		}
		else{
			flag = 1;
			return flag;
		}
	}
//	if(flag)
//		return flag;//
		//chck for %dwnloaded
	temp = head;
	flag =0;
	if((temp->percent_downloaded == 100.00) && temp->next){
		temp = temp->next;
	}
	else{
		flag = 2;
	}
	return flag;
	//now start to join
}
static float calc_percent(FILE * ptr)
{
	int i;
	for(i=0;i<65536;i++){
		if(*ptr == 0x04){	//0x04 is EOF....want to test this!
			break;
		}
		ptr += sizeof(char);
		i++;
	}
	return	(i/65536)*100;
}

/*****************************CHECK FILE*****************************************
* Func desc: checks whether part of the file is complete.
* arguments:
*@ struct file_part *head: the head pointer(filename)
*@ int part_num: to indicate which part number to chck.
*@enum chck_status....update status into this and return
*return: The function return enum status.
----------------------------------------------------------------------------------
*Function will be called by manager to chck if particular part is complete or not.
* The manager must call this function once for each part..???can this be made into a recursive function to check the entire file???
**********************************************************************************/
enum check_file(struct file_part *head,enum chck_status,int part_no)
{
	struct file_part *temp = head;
	FILE * save_dp = temp->data_ptr
	while(*temp->part_num != part_no){
		temp = temp->next;
	}
	printf("Checking part number %d",temp->part_num);

	temp->percent_downloaded = calc_percent(temp->data_ptr);

	temp->data_ptr = save_dp;
	if(temp->percent_downloaded == 0.00){
		return (chck_status = PENDING);
	}
	else if(temp->percent_downloaded == 100.00){
		return (chck_status = COMPLETE);
	}
	else if(temp->percent_downloaded < 100.00){
		return (chck_status = LEECHING);
	}
}

int main()
{
	FILE *fp;
	long int offset;
	long int fileSize;
	int noOfParts=0;
	int lpsize=0;
	char * filename="test207.avi";
	struct file_part *filehead;
	
	fp=fopen(filename,"r+");
	fseek (fp,0,SEEK_END);
  	fileSize = ftell(fp);
  	rewind (fp);
	
	noOfParts= (int) fileSize/PARTSIZE;
	lpsize=(int) fileSize%PARTSIZE;
	if(lpsize==0)
	{
		//do nothing
	}
	else
	{
		noOfParts=noOfParts+1;
	}
      
        filename = head; // filename itself is a head to linked list for that particular file.
	filehead=add_to_list(**filename,noOfParts,lpsize);

	print_list(filehead);
	
	
return 0;
}

void add_to_list(struct file_part **filename, int noOfParts, int lpsize)
{
  
struct file_part *r, *temp 
temp = *filename ;

	r = malloc ( sizeof ( struct file_part ) ) ;

       if (part_num == 0)

	r -> data = num ;
        /*

        struct file_part *next;

	char* filename;		//name of the file to which the part belongs
	int part_num;		//part number (can be used for somethng like hash checking)
	
	FILE *data_ptr;		//ptr to the file created for this part.ie whr the data of this part is stored.
				//file descriptor for FILE* data_ptr.

	//int offset;		//will hold the offset to the starting point of the part. each part being 64kb.
		
	struct seeder seeder_list[MAX_SEEDS];	//list of seeders.
	struct leecher leecher_list[MAX_LEECHES];	//
	
	float percent_downloaded;
	enum status{SEEDING,COMPLETE,LEECHING,PENDING}download;

        */

	/* if list is empty or if new node is to be inserted before the first node */

	if ( *q == NULL || ( *q ) -> data > num )
	{
		*q = r ;
		( *q ) -> link = temp ;
	}
	else
	{
		/* traverse the entire linked list to search the position to insert the 
		    new node */
		while ( temp != NULL )
		{
			if ( temp -> data <= num && ( temp -> link -> data > num || 
										temp -> link == NULL ))
			{
				r -> link = temp -> link ;
				temp -> link = r ;
				return ;
			}
			temp = temp -> link ;  /* go to the next node */
		}
	}


}

struct node
{
	int data ;
	struct node *link ;
} ;

void add ( struct node **, int ) ;
void display ( struct node * ) ;
int count ( struct node * ) ;
void delete ( struct node **, int ) ;

void main( )
{
	struct node *p ;
	p = NULL ;  /* empty linked list */

	add ( &p, 5 ) ;
	add ( &p, 1 ) ;
	add ( &p, 6 ) ;
	add ( &p, 4 ) ;
	add ( &p, 7 ) ;

	clrscr( ) ;
	display ( p ) ;
	printf ( "\nNo. of elements in Linked List = %d", count ( p ) ) ;
}

/* adds node to an ascending order linked list */
void add ( struct node **q, int num )
{
	struct node *r, *temp = *q ;

	r = malloc ( sizeof ( struct node ) ) ;
	r -> data = num ;

	/* if list is empty or if new node is to be inserted before the first node */
	if ( *q == NULL || ( *q ) -> data > num )
	{
		*q = r ;
		( *q ) -> link = temp ;
	}
	else
	{
		/* traverse the entire linked list to search the position to insert the 
		    new node */
		while ( temp != NULL )
		{
			if ( temp -> data <= num && ( temp -> link -> data > num || 
										temp -> link == NULL ))
			{
				r -> link = temp -> link ;
				temp -> link = r ;
				return ;
			}
			temp = temp -> link ;  /* go to the next node */
		}
	}
}


#endif	//DSTRUCT
